#include "QFtpDownloader.h"

#include <thread>
#include <chrono>
#include <qmessagebox.h>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <qfiledialog.h>
#include <qscopedpointer.h>



void QFtpDownloader::on_pushButton_upload_clicked()
{
    QString _temporary{ui.lineEdit_upload_local->text().trimmed()};
    QString _upload_remote{ui.lineEdit_upload_remote->text()};
    if (_temporary.isEmpty() || _upload_remote.isEmpty())
    {
        QMessageBox::warning(this, "warning", "please input related upload parameter");
        return;
    }
    _upload_remote.append(GetLocalFileName());
    if (m_ftp)
    {
        ListImplement(_upload_remote);
        my_sleep(10);
        bool _conn_flag{ false };
        if (m_remote_files.isEmpty())
        {
            _conn_flag = false;
        }
        else
        {
            if (JudgeFileExist())
                _conn_flag = true;
            else
                _conn_flag = false;
        }

        if (nullptr == m_file)
            m_file = new QFile(_temporary);
        Q_ASSERT(m_file);
        if (m_file->open(QIODevice::ReadOnly))
        {
            if (_conn_flag)
                m_ftp->conPut(m_file, _upload_remote);
            else
                m_ftp->put(m_file, _upload_remote);

        }
        else
        {
            QMessageBox::warning(this, "warning", "open file fail");
            ReleaseFile();
        }
    }
}

void QFtpDownloader::on_pushButton_download_clicked()
{
    QString _local_path{ui.lineEdit_download_local->text().trimmed()};
    QString _remote_path{ui.lineEdit_download_remote->text().trimmed()};
    if (_local_path.isEmpty() || _remote_path.isEmpty())
    {
        QMessageBox::warning(this, "warning", "please input vaild download parameter");
        return;
    }
    bool _conn_flag{ false };
    if (QFile::exists(_local_path))
        _conn_flag = true;
    else
        _conn_flag = false;
    if (nullptr == m_file)
        m_file = new QFile(_local_path);
    Q_ASSERT(m_file);
    if (m_ftp)
    {
        if (_conn_flag)
        {
            if (m_file->open(QIODevice::Append))
            {
                m_ftp->rawCommand(QString("REST %1").arg(m_file->size()));
                m_ftp->m_isConLoad = true;
                m_ftp->get(_remote_path, m_file);
            }
            else
            {
                QMessageBox::warning(this, "warning", "append file fail");
                ReleaseFile();
            }
        }
        else
        {
            if (m_file->open(QIODevice::WriteOnly))
            {
                m_ftp->get(_remote_path, m_file);
            }
            else
            {
                QMessageBox::warning(this, "warning", "open file fail");
                ReleaseFile();
            }
        }
    }//ftp
}

void QFtpDownloader::on_pushButton_continue_clicked()
{
    on_pushButton_upload_clicked();
}

void QFtpDownloader::on_pushButton_pause_clicked()
{
    if (m_ftp)
        m_ftp->abort();
}

void QFtpDownloader::on_toolButton_upload_clicked()
{
    QString _file_name{};
    if (_file_name = QFileDialog::getOpenFileName(this, "local file", QApplication::applicationDirPath(), "*.*", nullptr, QFileDialog::DontUseNativeDialog), !_file_name.isEmpty())
        ui.lineEdit_upload_local->setText(_file_name);
    GetLocalFileName();
}

void QFtpDownloader::on_toolButton_download_clicked()
{
    QString _file_name{};
    if (_file_name = QFileDialog::getSaveFileName(this, "save file", QApplication::applicationDirPath(), "*.*", nullptr, QFileDialog::DontUseNativeDialog), !_file_name.isEmpty())
        ui.lineEdit_download_local->setText(_file_name);
}

void QFtpDownloader::OnDataTransferProgress(qint64 curbytes, qint64 totalbytes)
{
    int _value = (curbytes / (double)totalbytes) * 100;
    ui.progressBar->setValue(_value);
}

void QFtpDownloader::OnCommandFinished(int temp, bool error)
{
	Q_UNUSED(temp);
	if (m_ftp)
	{
		auto _command = m_ftp->currentCommand();
		switch (_command)
		{
		case QFtp::ConnectToHost:
		{
			if (error)
			{
				QString _str{ QString("connect server error:[%1]").arg(m_ftp->errorString()) };
				QMessageBox::warning(this, "warning", _str);
			}
			else
			{
				m_ftp->login(m_user_name, m_password);
			}
		}
		break;
		case QFtp::Login:
		{
			if (error)
			{
				QString _str{ QString("login error:[%1]").arg(m_ftp->errorString()) };
				QMessageBox::warning(this, "warning", _str);
			}
		}
		break;
		case QFtp::Get:
        {
            if (error)
            {
                QString _str{QString("download detail:[%1]").arg(m_ftp->errorString())};
                QMessageBox::information(this, "information",_str );
            }
            ReleaseFile();
        }
			break;
		case QFtp::Put:
        {
            if (error)
            {
                QString _str{ QString("upload detail:[%1]").arg(m_ftp->errorString()) };
                QMessageBox::information(this, "information", _str);
            }
            ReleaseFile();
            InitProcessBar();
        }
			break;
		case QFtp::Close:
            QMessageBox::information(this, "information", "Close Client Connect");
			break;
		default:
			break;
		}

	}//ftp pointer

}

void QFtpDownloader::OnStateChanged(int flag)
{
    m_state = (QFtp::State)flag;
    if (QFtp::State::Unconnected == m_state)
    {
        if (m_ftp)
            m_ftp->abort();
        ReleaseFile();
    }
}

void QFtpDownloader::OnListInfo(const QUrlInfo& urlinfo)
{
    QString _data = urlinfo.name();
    if (m_remote_files.empty())
        m_remote_files.push_back(urlinfo);
    else
    {
        if (!m_remote_files.contains(urlinfo))
            m_remote_files.push_back(urlinfo);
    }
}

QFtpDownloader::QFtpDownloader(QWidget *parent)
    : QMainWindow(parent)
    , m_ftp{}
    ,m_state{QFtp::State::Unconnected}
    , m_user_name{}
    , m_password{}
    , m_file{}
{
    ui.setupUi(this);
    OnInitDialog();
}

QFtpDownloader::~QFtpDownloader()
{
}

bool QFtpDownloader::InitFtpConnect(const QString& host, quint16 port, const QString& username, const QString& password)
{
    if (m_ftp)
    {
        m_ftp->connectToHost(host, port);
        m_user_name = username;
        m_password = password;
        return true;
    }
    return false;
}

void QFtpDownloader::ListImplement(const QString&remote_path)
{
    if (m_ftp)
    {
        if (QFtp::State::LoggedIn == m_state)
        {
            m_remote_files.clear();
            QString _remote{ QStringLiteral("%1").arg(remote_path)};
            m_ftp->list(_remote);
        }
        else
        {
            if (QMessageBox::Yes == QMessageBox::question(this, "question", "not connect server,if reconnection?", QMessageBox::Yes | QMessageBox::No))
            {
                std::this_thread::sleep_for(std::chrono::milliseconds(300));
                OnInitDialog();
            }
        }
    }
}

QString QFtpDownloader::GetLocalFileName()
{
    QString _str{};
    QString _local_path{ ui.lineEdit_upload_local->text() };
    if (!_local_path.isEmpty())
    {
        _str = _local_path.mid(_local_path.lastIndexOf("/") + 1);
    }
    return _str;
}

void QFtpDownloader::my_sleep(unsigned int interval)
{
    if (0 == interval)
        return;
    unsigned int _count{ 0 };
    while (true)
    {
        if (interval <= _count)
            break;
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        _count++;
        QCoreApplication::processEvents();
    }
}

void QFtpDownloader::ReleaseFile()
{
    if (m_file)
    {
        m_file->close();
        delete m_file;
        m_file = nullptr;
    }
}

bool QFtpDownloader::JudgeFileExist()
{
    QString _filename{ GetLocalFileName() };
    for (const auto& i : m_remote_files)
    {
        if (0 == _filename.compare(i.name()))
            return true;
    }
    return false;
}

void QFtpDownloader::InitProcessBar() noexcept
{
    ui.progressBar->setValue(0);
}



void QFtpDownloader::OnInitDialog()
{
    InitFtp();
    InitFtpConnect("192.168.10.90",21, "liubaozheng", "lbz@1234");
    InitProcessBar();
}

void QFtpDownloader::InitFtp()
{
    if (nullptr == m_ftp)
        m_ftp = new QFtp(this);
    Q_ASSERT(m_ftp);
    connect(m_ftp, &QFtp::dataTransferProgress, this, &QFtpDownloader::OnDataTransferProgress, static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection));
    connect(m_ftp, &QFtp::commandFinished, this, &QFtpDownloader::OnCommandFinished,(Qt::ConnectionType)(Qt::AutoConnection | Qt::UniqueConnection));
    //connect(m_ftp, &QFtp::listInfo, this, [this]() {m_exist_flag = true; },Qt::DirectConnection);
    connect(m_ftp, &QFtp::listInfo, this,&QFtpDownloader::OnListInfo, (Qt::ConnectionType)(Qt::DirectConnection | Qt::UniqueConnection));
    connect(m_ftp, &QFtp::stateChanged, this, &QFtpDownloader::OnStateChanged,(Qt::ConnectionType)(Qt::AutoConnection | Qt::UniqueConnection));
}

void QFtpDownloader::on_pushButton_list_clicked()
{
    QString _remote_path{ ui.lineEdit_upload_remote->text() };
    if (_remote_path.isEmpty())
        return;
    ListImplement(_remote_path);
#if 0
    unsigned int _count{ 0 };
    while (true)
    {
        if (10 <= _count)
            break;
        QCoreApplication::processEvents();
        std::this_thread::sleep_for(std::chrono::milliseconds(50));
        _count++;
    }
#endif // 0
    my_sleep(10);

    if (!m_remote_files.isEmpty())
    {
        unsigned int _size = m_remote_files.size();
        QTableWidget* _ptr = ui.tableWidget;
        Q_ASSERT(_ptr);
        //_ptr->clear();
        _ptr->clearContents();
        _ptr->setRowCount(_size);
        int _row_cnt{ 0 };
        for (const auto& i : m_remote_files)
        {
            int _column{ 0 };
            _ptr->setItem(_row_cnt, _column++, new QTableWidgetItem(i.name()));
            _ptr->setItem(_row_cnt, _column++, new QTableWidgetItem(QString::number(i.size())));
            _ptr->setItem(_row_cnt, _column++, new QTableWidgetItem(i.owner()));
            _row_cnt++;
        }
    }
}
